package cn.gx.learn.security_boot_jwt_websocket.websocket_origin.endpoint;

import cn.gx.learn.security_boot_jwt_websocket.affairs.ws.event.WsEvent;
import cn.gx.learn.security_boot_jwt_websocket.aop.dal.date.Log;
import cn.gx.learn.security_boot_jwt_websocket.websocket_origin.dal.database.Message;
import cn.gx.learn.security_boot_jwt_websocket.base.dal.database.User;
import cn.gx.learn.security_boot_jwt_websocket.websocket_origin.config.GetHttpSessionConfig;
import cn.gx.learn.security_boot_jwt_websocket.websocket_origin.decoder.MessageDecoder;
import cn.gx.learn.security_boot_jwt_websocket.websocket_origin.service.MessageService;
import com.nimbusds.jose.JOSEException;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.text.ParseException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/ws", configurator = GetHttpSessionConfig.class,decoders = MessageDecoder.class)
@Component
@Slf4j
public class WebsocketEndPoint {
    private static MessageService messageService;
    @Autowired
    public void setMessageService(MessageService messageService) {
        WebsocketEndPoint.messageService = messageService;
    }

    private static final Map<Integer, Session> sessionMap = new ConcurrentHashMap<>();


    private static ApplicationContext applicationContext;
    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        WebsocketEndPoint.applicationContext = applicationContext;
    }

    @OnOpen
    public void onOpen(Session session, EndpointConfig endpointConfig) throws ParseException, JOSEException {
        User user= (User) endpointConfig.getUserProperties().get("user");
        sessionMap.put(user.getId(),session);
        log.info("用户"+user.getId()+"用户名："+user.getUsername()+"建立了连接,会话："+session);
        String s=messageService.sendMessageWhenOnline(session, user.getId());
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("ws_connection: ").append(user.getUsername()).append("建立连接 ").append("result：").append(s);
        publishEvent(stringBuilder.toString(), Log.Menutype.WSON);
    }

    @OnMessage
    public void onMessage(Message message, Session session) {

        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("ws_sendmessage: ");
        Session receiver_session = sessionMap.get(message.getReceiverId());
        stringBuilder.append("sender_id:").append(message.getSenderId()).append(", receiver:").append(message.getReceiverId()).append(" result:");
        if(receiver_session!=null){
            String s = messageService.sendMessageOnline(message, receiver_session);
            if("fail".equals(s)){
                publishEvent(stringBuilder.append(s).toString(), Log.Menutype.Message);
                session.getAsyncRemote().sendText("消息发送失败,对方已下线");
            }else publishEvent(stringBuilder.append(s).toString(), Log.Menutype.Message);

        }
        else {
            String s = messageService.sendMessageOffline(message);
            if("fail".equals(s)){
                publishEvent(stringBuilder.append(s).toString(), Log.Menutype.Message);
                session.getAsyncRemote().sendText("消息发送失败");
            }else {
                publishEvent(stringBuilder.append(s).toString(), Log.Menutype.Message);
            }
        }
    }
    public void publishEvent(String logMessage, Log.Menutype menuType){
        applicationContext.publishEvent(new WsEvent(new Log(logMessage),menuType));
    }

    @OnClose
    public void onClose(Session session) {
        Integer userIdToRemove = null;
        for (Map.Entry<Integer, Session> entry : sessionMap.entrySet()) {
            if (entry.getValue().equals(session)) {
                userIdToRemove = entry.getKey();
                sessionMap.remove(userIdToRemove);
                log.info("用户 {} 的连接已关闭，已从sessionMap中移除", userIdToRemove);
                break;
            }
        }

        try {
            if (session.isOpen()) {
                StringBuilder stringBuilder=new StringBuilder();
                stringBuilder.append("ws_close: ").append(sessionMap).append(" 关闭连接 ").append("result:success");
                session.close();
                publishEvent(stringBuilder.toString(), Log.Menutype.WSOUT);
            }
        } catch (IOException e) {
            StringBuilder stringBuilder=new StringBuilder();
            stringBuilder.append("ws_close: ").append(session.getId()).append(" 关闭连接 ").append("result:failed Exception:").append(e.getMessage());
            publishEvent(stringBuilder.toString(), Log.Menutype.WSOUT);
            log.error("关闭WebSocket连接时发生异常", e);
        }
    }



}
